;/***************************************************************************
; * Copyright (c) 2024 Microsoft Corporation 
; * 
; * This program and the accompanying materials are made available under the
; * terms of the MIT License which is available at
; * https://opensource.org/licenses/MIT.
; * 
; * SPDX-License-Identifier: MIT
; **************************************************************************/
;
;
;/**************************************************************************/ 
;/**************************************************************************/ 
;/**                                                                       */ 
;/** ThreadX Component                                                     */ 
;/**                                                                       */ 
;/**   Module Manager                                                      */ 
;/**                                                                       */ 
;/**************************************************************************/ 
;/**************************************************************************/ 

;
THUMB_MASK      EQU     0x20                    ; Thumb bit (5) of CPSR/SPSR
USR_MODE        EQU     0x10                    ; USR mode
SYS_MODE        EQU     0x1F                    ; SYS mode
#ifdef TX_ENABLE_FIQ_SUPPORT
CPSR_MASK       EQU     0xDF                    ; Mask initial CPSR, IRQ & FIQ ints enabled
#else
CPSR_MASK       EQU     0x9F                    ; Mask initial CPSR, IRQ ints enabled
#endif

;/**************************************************************************/ 
;/*                                                                        */ 
;/*  FUNCTION                                               RELEASE        */ 
;/*                                                                        */ 
;/*    _txm_module_manager_thread_stack_build          Cortex-A7/MMU/IAR   */ 
;/*                                                           6.3.0        */
;/*  AUTHOR                                                                */
;/*                                                                        */
;/*    Scott Larson, Microsoft Corporation                                 */
;/*                                                                        */
;/*  DESCRIPTION                                                           */ 
;/*                                                                        */ 
;/*    This function builds a stack frame on the supplied thread's stack.  */ 
;/*    The stack frame results in a fake interrupt return to the supplied  */ 
;/*    function pointer.                                                   */ 
;/*                                                                        */ 
;/*  INPUT                                                                 */ 
;/*                                                                        */ 
;/*    thread_ptr                            Pointer to thread control blk */ 
;/*    function_ptr                          Pointer to return function    */ 
;/*                                                                        */ 
;/*  OUTPUT                                                                */ 
;/*                                                                        */ 
;/*    None                                                                */ 
;/*                                                                        */ 
;/*  CALLS                                                                 */ 
;/*                                                                        */ 
;/*    None                                                                */ 
;/*                                                                        */ 
;/*  CALLED BY                                                             */ 
;/*                                                                        */ 
;/*    _tx_thread_create                     Create thread service         */ 
;/*                                                                        */ 
;/*  RELEASE HISTORY                                                       */ 
;/*                                                                        */ 
;/*    DATE              NAME                      DESCRIPTION             */
;/*                                                                        */
;/*  09-30-2020      Scott Larson            Initial Version 6.1           */
;/*  10-31-2023      Yajun Xia               Modified comment(s),          */
;/*                                            Added thumb mode support,   */
;/*                                            resulting in version 6.3.0  */
;/*                                                                        */
;/**************************************************************************/
;VOID   _txm_module_manager_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(TX_THREAD *, TXM_MODULE_INSTANCE *))
;{
    RSEG    .text:CODE:NOROOT(2)
    PUBLIC  _txm_module_manager_thread_stack_build
#ifdef THUMB_MODE
    THUMB
#else
    ARM
#endif
_txm_module_manager_thread_stack_build
;
;
;    /* Build a fake interrupt frame.  The form of the fake interrupt stack
;       on the Cortex-A7 should look like the following after it is built:
;       
;       Stack Top:      1           Interrupt stack frame type
;                       CPSR        Initial value for CPSR
;                       r0          Initial value for r0
;                       r1          Initial value for r1
;                       r2          Initial value for r2
;                       r3          Initial value for r3
;                       r4          Initial value for r4
;                       r5          Initial value for r5
;                       r6          Initial value for r6
;                       r7          Initial value for r7
;                       r8          Initial value for r8
;                       r9          Initial value for r9
;                       r10         Initial value for r10
;                       r11         Initial value for r11
;                       r12         Initial value for r12
;                       lr          Initial value for lr (r14)
;                       pc          Initial value for pc (r15)
;                       0           For stack backtracing
;
;    Stack Bottom: (higher memory address)  */
;
    LDR     r2, [r0, #16]                       ; Pickup end of stack area
    BIC     r2, r2, #7                          ; Ensure 8-byte alignment
    SUB     r2, r2, #76                         ; Allocate space for the stack frame
;
;    /* Actually build the stack frame.  */
;
    MOV     r3, #1                              ; Build interrupt stack type
    STR     r3, [r2, #0]                        ; Store stack type
    STR     r0, [r2, #8]                        ; Store initial r0 (thread pointer)
    LDR     r3, [r0, #8]                        ; Pickup thread info pointer (it's in the stack pointer location right now)
    STR     r3, [r2, #12]                       ; Store initial r1
    LDR     r3, [r3, #8]                        ; Pickup data base register
    STR     r3, [r2, #44]                       ; Store initial r9
    MOV     r3, #0                              ; Build initial register value
    STR     r3, [r2, #16]                       ; Store initial r2
    STR     r3, [r2, #20]                       ; Store initial r3
    STR     r3, [r2, #24]                       ; Store initial r4
    STR     r3, [r2, #28]                       ; Store initial r5
    STR     r3, [r2, #32]                       ; Store initial r6
    STR     r3, [r2, #36]                       ; Store initial r7
    STR     r3, [r2, #40]                       ; Store initial r8
    LDR     r3, [r0, #12]                       ; Pickup stack starting address
    STR     r3, [r2, #48]                       ; Store initial r10 (sl)
    MOV     r3, #0                              ; Build initial register value
    STR     r3, [r2, #52]                       ; Store initial r11
    STR     r3, [r2, #56]                       ; Store initial r12
    STR     r3, [r2, #60]                       ; Store initial lr
    STR     r1, [r2, #64]                       ; Store initial pc
    STR     r3, [r2, #68]                       ; 0 for back-trace
    MRS     r3, CPSR                            ; Pickup CPSR
    BIC     r3, #CPSR_MASK                      ; Mask mode bits of CPSR
    TST     r1, #1                              ; Test if THUMB bit set in initial PC
    IT      NE
    ORRNE   r3, #THUMB_MASK                     ; Set T bit if set
    LDR     r1, [r0, #156]                      ; Load tx_thread_module_current_user_mode
    TST     r1, #1                              ; Test if the flag is set
    ITE     EQ
    ORREQ   r3, #SYS_MODE                       ; Flag not set: Build CPSR, SYS mode, IRQ enabled
    ORRNE   r3, #USR_MODE                       ; Flag set: Build CPSR, USR mode, IRQ enabled
    STR     r3, [r2, #4]                        ; Store initial CPSR
;
;    /* Setup stack pointer.  */
;    thread_ptr -> tx_thread_stack_ptr =  r2;
;
    STR     r2, [r0, #8]                        ; Save stack pointer in thread's control block
    BX      lr                                  ; Return to caller
;}
    END

